/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Classifier.evaluation;

import au.com.bytecode.opencsv.CSVReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author kevin
 */
public class DataResultProcess {

    protected CSVReader m_CSVReader;
    protected List m_DataList;
    private boolean m_IsDataSorted = false;
    protected List m_CurvePoints = new ArrayList();;
    protected String m_FilePath;
    private double m_AUC;
    private double accuracy;
    private boolean isSoft;

    public String getFilePath() {
        return m_FilePath;
    }
    public double getAccuracy(){
        return this.accuracy;
    }
    public boolean isDataSoft(){
        return this.isSoft;
    }

    public DataResultProcess(String filepath) {
        try {
            //
            m_FilePath = filepath;
            m_CSVReader = new CSVReader(new FileReader(filepath));
            m_DataList = new ArrayList();
            m_DataList = m_CSVReader.readAll();
            // Vector v = new Vector();
            
            if (m_DataList != null) {
                if (this.isSoft()) {///结果集是软分类器产生的/////
                    this.isSoft=true;
                    this.sortData();
                    this.calculateCurvePoints();
                    this.setSoftAUC();
                }else{/////结果集是硬分类器产生的/////
                    this.isSoft=false;
                    this.calculateSinglePoint();
                    this.setDecreteAUC();
                }
                System.out.println("The AUC is : "+this.m_AUC);
            }
            ///test data///

//            int n=m_DataList.size();
//            int m=((String[])m_DataList.get(0)).length;
//            String[] line=new String[m];
//
//            for(int i=0;i<n;i++){
//                line = (String[]) m_DataList.get(i);
//                for(int j=0;j<m;j++){
//                    System.out.println(line[j]);
//                }
//            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public List getDataResult() {
        return this.m_DataList;
    }

    private void sortData() {
        Collections.sort(m_DataList, new DataCompare());
        m_IsDataSorted = true;
    }

    public double getAUC() {
        
        return m_AUC;
    }

    private void calculateCurvePoints() {
        int P = 0, tp = 0;
        int N = 0, fp = 0;
        int i = m_DataList.size();
        boolean theClass;
        boolean[] classes = new boolean[i];
        for (int j = 0; j < i; j++) {
            theClass = Boolean.parseBoolean(((String[]) m_DataList.get(j))[0]);
            classes[j] = theClass;
            if (theClass) {
                P += 1;//计算正例数
            } else {
                N += 1;//计算负例数
            }
        }
        for (int j = 0; j < i; j++) {
            //theClass = Boolean.parseBoolean(((String[])m_DataList.get(j-1))[0]);
            if (classes[j]) {
                tp += 1;
            } else {
                fp += 1;
            }
            //设置曲线描点值
            double[] point = new double[2];
            point[0] = (double) fp / N;
            point[1] = (double) tp / P;
            System.out.println(point[0] + "  " + point[1]);
            m_CurvePoints.add(point);
        }
        //计算准确率//
    }
    private void calculateSinglePoint(){
        int size = m_DataList.size();
        String[] line = new String[2];
        boolean theClass;
        double probability=0;
        double P=0, N=0, TP=0, FP=0, TN=0, FN=0;
        for(int i=0;i<size;i++){
            line = (String[])m_DataList.get(i);
            theClass = Boolean.parseBoolean(line[0]);
            probability = Double.parseDouble(line[1]);
            if(theClass){//实例为正例
                P+=1;
                if(probability==1){
                    TP+=1;
                }else{
                    FN+=1;
                }
            }else{//实例为负例
                N+=1;
                if(probability==1){
                    FP+=1;
                }else{
                    TN+=1;
                }
            }
        }
       // double fpr = FP/N;
        //double tpr = TP/P;
        double[] points = {FP/N,TP/P};
        double[] origin = new double[2];
        origin[0]=origin[1]=0;
        double[] endPoint = new double[]{1,1};
        m_CurvePoints.add(origin);
        m_CurvePoints.add(points);
        m_CurvePoints.add(endPoint);
        //计算准确率//
        this.accuracy=(TP+TN)/(P+N);
    }
    public List getCurvePoints() {


        int size = m_CurvePoints.size();
        for (int i = 0; i < size; i++) {
            double[] temp = (double[]) (m_CurvePoints.get(i));
            System.out.println(temp[0] + "  " + temp[1]);
        }
        return this.m_CurvePoints;
    }

    ///判断是否是软分类器///
    private boolean isSoft() {
        int size = m_DataList.size();
        String[] line = new String[2];
        double probability = 0;
        boolean issoft = false;
        for (int i = 0; i < size; i++) {
            line = (String[]) m_DataList.get(i);
            probability = Double.parseDouble(line[1]);
            if (probability != 1 && probability != 0) {
                issoft = true;
                System.out.println("soft classifier");
                break;
            }
        }
        if(issoft==false){
            System.out.println("It's Decrete classifier");
        }
        return issoft;
    }

    public static void main(String[] args) {
        DataResultProcess drp = new DataResultProcess("C:\\Users\\kevin\\Desktop\\Files\\myfile.csv");
        double temp = drp.getAUC();
        System.out.println("The area under the curve is : " + temp);
        drp.calculateCurvePoints();
        //drp.getCurvePoints();
        System.exit(0);
    }

    private void setSoftAUC() {
        if (!m_IsDataSorted) {
            this.sortData();
        }
        //计算S0的值
        int s0 = 0;
        int n0 = 0;//正例数
        int n1 = 0;//负例数
        Iterator it = m_DataList.iterator();
        int k = m_DataList.size();
        boolean theClass;
        while (it.hasNext()) {
            String[] line = (String[]) it.next();
            theClass = Boolean.parseBoolean(line[0]);
            if (theClass) {
                s0 += k;
                n0 += 1;
            } else {
                n1 += 1;
            }
            k--;
        }
        System.out.println("n0=" + n0 + "  n1=" + n1 + " and s0=" + s0);
        double result = 0;
        if (n0 != 0 && n1 != 0) {
            result = (double) (s0 - n0 * (n0 + 1) / 2) / (n0 * n1);
        }
        this.m_AUC=result;
    }

    private void setDecreteAUC() {
        double[] line = (double[])this.m_CurvePoints.get(1);
        double result = (1+line[1]-line[0])/2;
        this.m_AUC=result;
    }

    class DataCompare implements Comparator {

        public int compare(Object a, Object b) {
            String[] sa = (String[]) a;
            String[] sb = (String[]) b;
            int n = 1;
            double i = Double.parseDouble(sa[n]);
            double j = Double.parseDouble(sb[n]);
            if (i > j) {
                return -1;
            } else if (i < j) {
                return 1;
            } else {
                return 0;
            }
        }
    }
}
